// internal/api/handlers/console_handler.go
package handlers

import (
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/sirupsen/logrus"
	"github.com/yourusername/virt-manager-go/internal/service"
)

// ConsoleHandler 控制台处理器（统一管理 Serial/VNC/SPICE）
type ConsoleHandler struct {
	serialProxy   *service.SerialProxy
	graphicsProxy *service.GraphicsProxy
	logger        *logrus.Logger
}

func NewConsoleHandler(
	serialProxy *service.SerialProxy,
	graphicsProxy *service.GraphicsProxy,
	logger *logrus.Logger,
) *ConsoleHandler {
	return &ConsoleHandler{
		serialProxy:   serialProxy,
		graphicsProxy: graphicsProxy,
		logger:        logger,
	}
}

// ===== 串行控制台 API =====

// GetSerialConsoleInfo 获取串行控制台信息
//
//	@Summary	Get serial console connection info
//	@Tags		Console
//	@Param		connection	query		string					false	"Connection ID"
//	@Param		name		query		string					true	"VM Name"
//	@Success	200			{object}	map[string]interface{}	"{"data": object}"
//	@Failure	500			{object}	map[string]interface{}	"Internal Server Error"
//	@Router		/console/serial/info [get]
func (h *ConsoleHandler) GetSerialConsoleInfo(c *gin.Context) {
	connID := c.Query("connection")
	vmName := c.Query("name")
	if vmName == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "name query parameter is required"})
		return
	}

	h.logger.Infof("Getting serial console info for VM %s on connection %s", vmName, connID)

	info, err := h.serialProxy.GetSerialInfo(c.Request.Context(), connID, vmName)
	if err != nil {
		h.logger.WithError(err).Error("Failed to get serial console info")
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"data": info})
}

// HandleSerialConsoleWebSocket 处理串行控制台 WebSocket 连接
//
//	@Summary	Connect to serial console via WebSocket
//	@Tags		Console
//	@Param		connection	query	string	false	"Connection ID"
//	@Param		name		query	string	true	"VM Name"
//	@Param		token		query	string	true	"Access Token"
//	@Router		/console/serial [get]
func (h *ConsoleHandler) HandleSerialConsoleWebSocket(c *gin.Context) {
	connID := c.Query("connection")
	vmName := c.Query("name")
	if vmName == "" {
		// 错误信息在代理内部处理
		h.logger.Error("VM name is required")
		return
	}

	if err := h.serialProxy.HandleSerialWebSocket(c.Writer, c.Request, connID, vmName); err != nil {
		h.logger.WithError(err).Error("Serial console WebSocket handler error")
		// WebSocket 已经升级，不能再返回 HTTP 错误
	}
}

// ListSerialSessions 列出活跃的串行控制台会话
func (h *ConsoleHandler) ListSerialSessions(c *gin.Context) {
	sessions := h.serialProxy.GetActiveSessions()
	c.JSON(http.StatusOK, gin.H{
		"data":  sessions,
		"count": len(sessions),
	})
}

// GetSerialSession 获取串行控制台会话信息
func (h *ConsoleHandler) GetSerialSession(c *gin.Context) {
	sessionID := c.Param("session_id")

	session, err := h.serialProxy.GetSessionInfo(sessionID)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"data": session})
}

// CloseSerialSession 关闭串行控制台会话
func (h *ConsoleHandler) CloseSerialSession(c *gin.Context) {
	sessionID := c.Param("session_id")

	if err := h.serialProxy.CloseSession(sessionID); err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "Session closed"})
}

// CloseVMSerialSessions 关闭虚拟机的所有串行控制台会话
//
//	@Summary	Close all serial sessions for a VM
//	@Tags		Console
//	@Param		connection	query		string	true	"Connection ID"
//	@Param		name		query		string	true	"VM Name"
//	@Success	200			{object}	map[string]interface{}
//	@Router		/console/serial/sessions [delete]
func (h *ConsoleHandler) CloseVMSerialSessions(c *gin.Context) {
	connID := c.Query("connection")
	vmName := c.Query("name")
	if vmName == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "name query parameter is required"})
		return
	}

	count := h.serialProxy.CloseSessionsByVM(connID, vmName)

	c.JSON(http.StatusOK, gin.H{
		"message": "Sessions closed",
		"count":   count,
	})
}

// GetSerialProxyStats 获取串行控制台代理统计信息
func (h *ConsoleHandler) GetSerialProxyStats(c *gin.Context) {
	stats := h.serialProxy.GetStats()
	c.JSON(http.StatusOK, gin.H{"data": stats})
}

// RevokeSerialToken 撤销串行控制台访问令牌
func (h *ConsoleHandler) RevokeSerialToken(c *gin.Context) {
	token := c.Param("token")

	if h.serialProxy.RevokeToken(token) {
		c.JSON(http.StatusOK, gin.H{"message": "Token revoked"})
	} else {
		c.JSON(http.StatusNotFound, gin.H{"error": "Token not found"})
	}
}

// ===== VNC 控制台 API =====

// GetVNCInfo 获取 VNC 连接信息
//
//	@Summary	Get VNC connection info
//	@Tags		Console
//	@Param		connection	query		string					false	"Connection ID"
//	@Param		name		query		string					true	"VM Name"
//	@Success	200			{object}	map[string]interface{}	"{"data": object}"
//	@Failure	500			{object}	map[string]interface{}	"Internal Server Error"
//	@Router		/console/vnc/info [get]
func (h *ConsoleHandler) GetVNCInfo(c *gin.Context) {
	connID := c.Query("connection")
	vmName := c.Query("name")
	if vmName == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "name query parameter is required"})
		return
	}

	info, err := h.graphicsProxy.GetVNCInfo(c.Request.Context(), connID, vmName)
	if err != nil {
		h.logger.WithError(err).Error("Failed to get VNC info")
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"data": info})
}

// HandleVNCWebSocket 处理 VNC WebSocket 连接
//
//	@Summary	Connect to VNC via WebSocket
//	@Tags		Console
//	@Param		connection	query	string	false	"Connection ID"
//	@Param		name		query	string	true	"VM Name"
//	@Param		token		query	string	true	"Access Token"
//	@Router		/console/vnc [get]
func (h *ConsoleHandler) HandleVNCWebSocket(c *gin.Context) {
	connID := c.Query("connection")
	vmName := c.Query("name")
	if vmName == "" {
		h.logger.Error("VM name is required")
		return
	}

	if err := h.graphicsProxy.HandleVNCWebSocket(c.Writer, c.Request, connID, vmName); err != nil {
		h.logger.WithError(err).Error("VNC WebSocket handler error")
	}
}

// ===== SPICE 控制台 API =====

// GetSPICEInfo 获取 SPICE 连接信息
//
//	@Summary	Get SPICE connection info
//	@Tags		Console
//	@Param		connection	query		string					false	"Connection ID"
//	@Param		name		query		string					true	"VM Name"
//	@Success	200			{object}	map[string]interface{}	"{"data": object}"
//	@Failure	500			{object}	map[string]interface{}	"Internal Server Error"
//	@Router		/console/spice/info [get]
func (h *ConsoleHandler) GetSPICEInfo(c *gin.Context) {
	connID := c.Query("connection")
	vmName := c.Query("name")
	if vmName == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "name query parameter is required"})
		return
	}

	info, err := h.graphicsProxy.GetSPICEInfo(c.Request.Context(), connID, vmName)
	if err != nil {
		h.logger.WithError(err).Error("Failed to get SPICE info")
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"data": info})
}

// HandleSPICEWebSocket 处理 SPICE WebSocket 连接
//
//	@Summary	Connect to SPICE via WebSocket
//	@Tags		Console
//	@Param		connection	query	string	false	"Connection ID"
//	@Param		name		query	string	true	"VM Name"
//	@Param		token		query	string	true	"Access Token"
//	@Router		/console/spice [get]
func (h *ConsoleHandler) HandleSPICEWebSocket(c *gin.Context) {
	connID := c.Query("connection")
	vmName := c.Query("name")
	if vmName == "" {
		h.logger.Error("VM name is required")
		return
	}

	if err := h.graphicsProxy.HandleSPICEWebSocket(c.Writer, c.Request, connID, vmName); err != nil {
		h.logger.WithError(err).Error("SPICE WebSocket handler error")
	}
}

// ListGraphicsSessions 列出图形控制台会话
func (h *ConsoleHandler) ListGraphicsSessions(c *gin.Context) {
	sessions := h.graphicsProxy.GetActiveSessions()

	sessionInfos := make([]gin.H, 0, len(sessions))
	for _, s := range sessions {
		sessionInfos = append(sessionInfos, gin.H{
			"id":   s.GetID(),
			"name": s.GetVMName(),
			"type": s.GetSessionType(),
		})
	}

	c.JSON(http.StatusOK, gin.H{
		"data":  sessionInfos,
		"count": len(sessionInfos),
	})
}

// ===== 通用控制台 API =====

// GetConsoleInfos 获取虚拟机支持的控制台类型
//
//	@Summary	Get supported console infos for a VM
//	@Tags		Console
//	@Param		connection	query		string	true	"Connection ID"
//	@Param		name		query		string	true	"VM Name"
//	@Success	200			{object}	map[string]interface{}
//	@Router		/console/info [get]
func (h *ConsoleHandler) GetConsoleInfos(c *gin.Context) {
	connID := c.Query("connection")
	vmName := c.Query("name")
	if vmName == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "name query parameter is required"})
		return
	}

	types := make([]string, 0)
	availableConsoles := make(map[string]interface{})

	// 检查串行控制台
	if serialInfo, err := h.serialProxy.GetSerialInfo(c.Request.Context(), connID, vmName); err == nil {
		types = append(types, "serial")
		availableConsoles["serial"] = serialInfo
	}

	// 检查 VNC
	if vncInfo, err := h.graphicsProxy.GetVNCInfo(c.Request.Context(), connID, vmName); err == nil {
		types = append(types, "vnc")
		availableConsoles["vnc"] = vncInfo
	}

	// 检查 SPICE
	if spiceInfo, err := h.graphicsProxy.GetSPICEInfo(c.Request.Context(), connID, vmName); err == nil {
		types = append(types, "spice")
		availableConsoles["spice"] = spiceInfo
	}

	c.JSON(http.StatusOK, gin.H{
		"name":     vmName,
		"types":    types,
		"consoles": availableConsoles,
	})
}
